package com.atguigu.gulimall.order.config;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;


@Configuration
public class RabbitMqConfig {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 定制RabbitTemplate
     * 1、服务器收到消息就回调
     *      1、publisher-confirm-type: correlated
     *      2、设置确认回调ConfirmCallback
     * 2、消息正确抵达队列进行回调
     *      1、#开启发送端消息抵达队列确认
     *     publisher-returns: true
     *     template:
     *       mandatory: true  #只要抵达队列，以异步模式优先回调我们这个returnConfirm
     *      2、设置确认回调
     * 3、消费端（保证每一个消息被正确消费,此时才可以broken删除这个消息）
     *      1、默认是自动确认的，只要消息接收到，客户端会自动确认
     */
    @PostConstruct //MyRabbitConfig对象创建完以后，调用这个方法
    public void initRabbitTemplate(){
        //设置确认回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             *
             * @param correlationData 当前消息的唯一关联数据（这个消息的唯一id）
             * @param b 消息是否成功收到
             * @param s  失败的原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                System.out.println("confirm...correlationData："+correlationData+"ack:==="+b+"s====>"+s);

            }
        });

        //设置消息抵达队列的确认回调
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            /**
             * 只要消息没有投递给指定队列，就触发这个失败回调
             * @param returnedMessage
             */
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                //投递失败的消息，详细信息
                Message message = returnedMessage.getMessage();
                //回复的状态码
                int replyCode = returnedMessage.getReplyCode();
                //回复的文本内容
                String replyText = returnedMessage.getReplyText();
//                当时这个消息发给哪个交换机
                String exchange = returnedMessage.getExchange();
                //当时这个消息用哪个路由键
                String routingKey = returnedMessage.getRoutingKey();

                System.out.println("message====>"+message+"replyCode====>"+replyCode+"replyText=====>"
                        +replyText+"exchange=====>"+exchange+ "routingKey====>"+routingKey);
            }
        });
    }

}

@Configuration
class MyMessageConverterConfig {
    /**
     * 使用JSON序列化机制，进行消息转换
     * @return
     */
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}
